home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
024
/
csh
/
execom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
10KB
|
439 lines
/*
* EXECOM.C
*
* Matthew Dillon, 28 Apr 1986
*
* This code is particular hacked up and needs re-writing.
*
*/
#include "shell.h"
struct COMMAND {
int (*func)();
short minargs;
short stat;
short val;
char *name;
};
struct MLIST {
struct MLIST *next;
};
#define F_EXACT 0
#define F_ABBR 1
extern char *breakout();
extern int do_run(), do_number();
extern int do_quit(), do_set_var(), do_unset_var();
extern int do_echo(), do_source(), do_mv();
extern int do_cd(), do_rm(), do_mkdir(), do_history();
extern int do_mem(), do_cat(), do_dir();
extern int do_foreach(), do_return(), do_if(), do_label(), do_goto();
extern int do_failat(), do_checkbrk(), do_inc();
extern int do_input(), do_ver();
static struct MLIST *Mlist;
static struct COMMAND Command[] = {
do_run , 0, 0, 0 , "\001",
do_number , 0, 0, 0 , "\001",
do_quit , 0, 0, 0 , "quit",
do_set_var , 0, 0, LEVEL_SET , "set",
do_unset_var, 0, 0, LEVEL_SET , "unset",
do_set_var , 0, 0, LEVEL_ALIAS, "alias",
do_unset_var, 0, 0, LEVEL_ALIAS, "unalias",
do_echo , 0, 0, 0 , "echo",
do_source , 0, 0, 0 , "source",
do_mv , 2, 0, 0 , "mv",
do_cd , 0, 0, 0 , "cd",
do_rm , 0, 0, 0 , "rm",
do_mkdir , 0, 0, 0 , "mkdir",
do_history , 0, 0, 0 , "history",
do_mem , 0, 0, 0 , "mem",
do_cat , 0, 0, 0 , "cat",
do_dir , 0, 0, 0 , "dir",
do_dir , 0, 0, -1 , "devinfo",
do_foreach , 3, 0, 0 , "foreach",
do_return , 0, 0, 0 , "return",
do_if , 1, 1, 0 , "if",
do_if , 0, 1, 1 , "else",
do_if , 0, 1, 2 , "endif",
do_label , 1, 1, 0 , "label",
do_goto , 1, 0, 0 , "goto",
do_failat , 1, 0, 0 , "failat",
do_checkbrk , 0, 0, 0 , "checkbreak",
do_inc , 1, 0, 1 , "inc",
do_inc , 1, 0, -1, "dec",
do_input , 1, 0, 0, "input",
do_ver , 0, 0, 0, "version",
NULL , 0, 0, 0 , NULL };
static char *
mpush(amount)
{
struct MLIST *ml;
ml = (struct MLIST *)malloc (amount + sizeof(*Mlist));
ml->next = Mlist;
Mlist = ml;
return ((char *)Mlist + sizeof(*Mlist));
}
static char *
mpop()
{
char *old = NULL;
if (Mlist == NULL) {
puts ("Internal MLIST error");
fflush (stdout);
} else {
old = (char *)Mlist + sizeof(*Mlist);
Free (Mlist);
Mlist = Mlist->next;
}
return (old);
}
mrm()
{
while (Mlist) {
Free (Mlist);
Mlist = Mlist->next;
}
}
exec_command(base)
char *base;
{
char *str;
int i;
if (!H_stack)
add_history(base);
strcpy (str = mpush(strlen(base) + 1), base);
i = e_command(str);
if (mpop() != str) {
puts ("POP ERROR");
fflush (stdout);
}
return (1);
}
static
e_command(base)
char *base;
{
char *com, *start, *avline, *alias;
char *s1, *s2, *s3, *s4;
int flag = 0;
int i, pcount, len, ccno;
loop:
com = breakout (&base, &flag);
if (*com == '\0') {
if (flag & FL_EOL)
return (1);
goto loop;
}
alias = NULL;
if ((ccno = find_command(com, F_EXACT)) < 0) {
switch (flag & FL_MASK) {
case FL_BANG:
alias = get_history (com);
replace_head (alias, base, flag);
break;
case FL_DOLLAR:
alias = get_var (LEVEL_SET, com + 1);
break;
default:
alias = get_var (LEVEL_ALIAS, com);
break;
}
if (alias == NULL) {
if ((ccno = find_command (com, F_ABBR)) < 0) {
printf ("%s Command Not Found\n", com);
return (-1);
} else {
goto good_command;
}
}
if (*alias == '%')
goto good_command;
start = (!(flag & FL_EOC)) ? base : "";
while (!(flag & FL_EOC)) {
flag = FL_OVERIDE;
breakout (&base, &flag);
}
com = mpush (strlen(alias) + strlen(start) + 2);
strcpy (com, alias);
strcat (com, " ");
strcat (com, start);
i = e_command (com);
if (mpop() != com)
puts ("ME BAE ERROR");
if (i < 0)
return (-1);
if (flag & FL_EOL)
return (1);
goto loop;
}
good_command:
if (ccno < 0 || Command[ccno].stat == 0) {
if (Disable) {
while (!(flag & FL_EOC))
breakout (&base, &flag);
goto eocc;
}
}
pcount = 0;
i = pcount = 0;
av[i] = mpush (strlen(com) + 1);
++pcount;
strcpy (av[i++], com);
while (!(flag & FL_EOC)) {
com = breakout (&base, &flag);
if (*com == '\0')
continue;
switch (flag & FL_MASK) {
case FL_DOLLAR:
av[i] = get_var (LEVEL_SET, com + 1);
if (av[i] == NULL)
av[i] = com;
av[i] = strcpy(mpush (strlen(av[i]) + 1), av[i]);
++pcount;
break;
case FL_QUOTE:
default:
av[i] = com;
break;
}
if (flag & FL_IDOLLAR) {
for (s1 = av[i]; *s1 && *s1 != '$'; ++s1);
if (*s1) {
*s1 = '\0';
s1 = get_var (LEVEL_SET, s1 + 1);
if (s1) {
register char *scr_str = mpush(strlen(av[i])+strlen(s1)+1);
++pcount;
strcpy (scr_str, av[i]);
strcat (scr_str, s1);
av[i] = scr_str;
}
}
}
if (flag & FL_WILD) { /* av[i] has a wild card, expand it */
int eac;
char **eav, **ebase;
eav = ebase = expand (av[i], &eac); /* returns malloc'd av list */
if (eav == NULL) {
puts ("Null expansion");
goto fail;
}
if (i + eac > MAXAV - 2) {
free_expand (ebase);
goto avovr;
}
for (; eac; --eac, ++eav) {
av[i++] = strcpy(mpush(strlen(*eav)+1), *eav);
++pcount;
}
--i;
free_expand (ebase);
}
if (++i > MAXAV - 2) {
avovr:
puts ("AV overflow");
goto fail;
}
}
av[i] = NULL;
ac = i;
for (len = 0, i = 0; i < ac; ++i)
len += strlen(av[i]) + 1;
avline = mpush (len + 1);
*avline = '\0';
for (i = 0; i < ac; ++i) {
strcat (avline, av[i]);
if (i + 1 < ac)
strcat (avline, " ");
}
if (*alias) {
for (s2 = alias; *s2 && *s2 != ' '; ++s2);
if (*s2) {
*s2 = '\0';
s3 = strcpy(mpush(strlen(next_word(avline))+1), next_word(avline));
s4 = strcpy(malloc(strlen(alias)), alias + 1);
set_var (LEVEL_SET, s4, s3);
*s2 = ' ';
s1 = strcpy(mpush(strlen(s2)+1), s2);
i = e_command (s1);
unset_var (LEVEL_SET, s4);
free (s4);
if (mpop() != s1)
puts ("AL-LINE ERROR");
mpop();
}
} else {
i = -1;
if (ac < Command[ccno].minargs + 1)
ierror (NULL, 500);
else
i = (*Command[ccno].func)(avline, Command[ccno].val);
}
if (mpop() != avline) {
puts ("AVLINE ERROR");
fail:
i = -1;
}
while (pcount--)
mpop();
if (i < 0)
return (i);
eocc:
if (flag & FL_EOL)
return (1);
goto loop;
}
static char *
breakout(base, flag)
register int *flag;
char **base;
{
register char *str, *scr;
register int oflag = *flag;
loop:
*flag = 0;
str = *base;
while (*str == ' ' || *str == 9)
++str;
switch (*str) {
case '\0':
*flag = FL_EOC | FL_EOL;
*base = str;
return (str);
case '*':
case '?':
*flag = FL_WILD;
break;
case ';':
*flag = FL_EOC;
*str = '\0';
*base = str + 1;
return (str);
case '\"':
*flag = FL_QUOTE;
break;
case '$':
*flag = FL_DOLLAR;
break;
case '%':
*flag = FL_PERCENT;
break;
case '!':
*flag = FL_BANG;
break;
default:
break;
}
scr = str;
for (;;) {
switch (*scr) {
case '$':
if (scr != str)
*flag |= FL_IDOLLAR;
++scr;
break;
case '*':
case '?':
*flag |= FL_WILD;
++scr;
break;
case ' ':
case 9:
if (!(oflag & FL_OVERIDE))
*scr = '\0';
*base = scr + 1;
return (str);
case '\"': /* Quote */
del_char(scr);
while (*scr && *scr != '\"') {
if (*scr == '\\') {
del_char(scr);
if (*scr)
++scr;
} else {
++scr;
}
}
if (*scr == '\"')
del_char(scr);
break;
case '\0':
*flag |= FL_EOL | FL_EOC;
*base = scr;
return (str);
case ';':
*flag |= FL_EOC;
*base = scr + 1;
*scr = '\0';
return (str);
case '^':
++scr;
if (*scr) {
*(scr - 1) = *scr & 0x1f;
del_char (scr);
}
break;
case '\\':
del_char(scr);
if (*scr)
++scr;
break;
default:
++scr;
}
}
}
del_char(str)
register char *str;
{
for (; *str; ++str)
str[0] = str[1];
}
static
find_command(str, arg)
char *str;
{
int i;
int len = strlen(str);
if (*str >= '0' && *str <= '9')
return (1);
for (i = 0; Command[i].func; ++i) {
if (strncmp (str, Command[i].name, len) == 0) {
if (arg == F_ABBR)
return (i);
if (strcmp (str, Command[i].name) == 0)
return (i);
return (-1);
}
}
if (arg == F_ABBR)
return (0);
return (-1);
}